home *** CD-ROM | disk | FTP | other *** search
- /*
- WASTE Demo Project:
- Window Handling
-
- Copyright © 1993-1995 Marco Piovanelli
- All Rights Reserved
-
- C port by John C. Daub
- */
-
-
- #ifndef __ALIASES__
- #include <Aliases.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef _LongCoords_
- #include "LongCoords.h"
- #endif
-
- #ifndef __WEDEMOAPP__
- #include "WEDemoIntf.h"
- #endif
-
- // some consts used by DoGrow()
-
- enum {
- kMinWindowWidth = 200,
- kMinWindowHeight = 80
- };
-
- // static variables
-
- static WEScrollUPP sWEScroller;
- static WETranslateDragUPP sWEDragTranslator;
- static ControlActionUPP sScrollProc;
- static short sScrollStep; // how many pixels to scroll (used by ScrollProc)
-
-
- static void CalcGrowIconRect( WindowRef window, Rect *iconRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- iconRect->top = portRect.bottom - (kBarWidth - 2);
- iconRect->left = portRect.right - (kBarWidth - 2);
- iconRect->bottom = portRect.bottom;
- iconRect->right = portRect.right;
- }
-
- static void CalcTextRect( WindowRef window, Rect *textRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- textRect->top = 0;
- textRect->left = 0;
- textRect->bottom = portRect.bottom - (kBarWidth - 1);
- textRect->right = portRect.right - (kBarWidth - 1);
- InsetRect( textRect, kTextMargin, kTextMargin );
- }
-
- static void CalcScrollBarRect( WindowRef window, VHSelect axis, Rect *barRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- switch ( axis )
- {
- case v:
- barRect->top = -1;
- barRect->left = portRect.right - (kBarWidth - 1);
- barRect->bottom = portRect.bottom - (kBarWidth - 2);
- barRect->right = portRect.right + 1;
- break;
-
- case h:
- barRect->top = portRect.bottom - (kBarWidth - 1);
- barRect->left = -1;
- barRect->bottom = portRect.bottom + 1;
- barRect->right = portRect.right - (kBarWidth - 2 );
- break;
-
- default:
- break;
- }
- }
-
- /*
- the standard Toolbox trap _DrawGrowIcon draws two lines from the grow icon
- to the left and top margins of the window's content area
- these additional lines may create ugly dirt, so we use this routine to temporarily
- set the clip region to the grow icon rect.
-
- in addition, if validate is true, we call _ValidRect on the icon rect
- */
-
- static void MyDrawGrowIcon( WindowRef window, Boolean validate )
- {
- GrafPtr savePort;
- RgnHandle saveClip;
- Rect r;
-
- // save port and set thePort to wind
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- // save the clip region
-
- saveClip = NewRgn();
- GetClip( saveClip );
-
- // calculate the grow icon rect
-
- CalcGrowIconRect( window, &r );
-
- // set clip region to grow icon rect
-
- ClipRect( &r );
-
- // call _DrawGrowIcon
-
- DrawGrowIcon( window );
-
- // if validate is true, remove the grow icon rect from the update region
-
- if ( validate )
- ValidRect( &r );
-
- // restore old clip region
-
- SetClip( saveClip );
- DisposeRgn( saveClip );
-
- // restore old port
-
- SetPort( savePort );
-
- return;
- }
-
- static void ScrollBarChanged( WindowRef window )
- {
- // scroll text to reflect new scroll bar setting
-
- WEReference we;
- LongRect viewRect, destRect;
-
- we = GetWindowWE(window);
- WEGetViewRect( &viewRect, we );
- WEGetDestRect( &destRect, we );
- WEScroll( viewRect.left - destRect.left - LCGetValue( ((* GetWindowDocument(window))->scrollBars).h),
- viewRect.top - destRect.top - LCGetValue( ((* GetWindowDocument(window))->scrollBars).v), we );
-
- return;
- }
-
- static void AdjustBars( WindowRef window )
- {
- DocumentHandle hDocument;
- WEReference we;
- GrafPtr savePort;
- LongRect viewRect, destRect;
- long value;
- long max;
- ControlRef bar;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument(window);
- we = (*hDocument)->we;
-
- // get the view and destination rectangle
-
- WEGetViewRect( &viewRect, we );
- WEGetDestRect( &destRect, we );
-
- // do the vertical axis
-
- // get scroll bar handle
-
- bar = ((*hDocument)->scrollBars).v;
-
- // calculate new scroll bar settings
-
- // NOTE: (destRect.bottom - destRect.top) always equals the total text height because
- // WASTE automatically updates destRect.bottom whenever line breaks are recalculated
-
- value = viewRect.top - destRect.top;
-
- max = value + (destRect.bottom - viewRect.bottom);
-
- // make sure max is always non-negative
-
- if ( max <= 0 )
- max = 0;
-
- // reset the scroll bar
-
- LCSetMax( bar, max );
- LCSetValue( bar, value );
-
- // if value exceeds max then the bottom of the destRect is above
- // the bottom of the view rectangle: we need to scroll the text downward
-
- if ( value > max )
- ScrollBarChanged( window );
-
- // now do the horizontal axis
-
- // get scroll bar handle
-
- bar = ((*hDocument)->scrollBars).h;
-
- // calculate new scroll bar settings
-
- // NOTE: (destRect.bottom - destRect.top) always equals the total text height because
- // WASTE automatically updates destRect.bottom whenever line breaks are recalculated
-
- value = viewRect.left - destRect.left;
-
- max = value + (destRect.right - viewRect.right);
-
- // make sure max is always non-negative
-
- if ( max <= 0 )
- max = 0;
-
- // reset the scroll bar
-
- LCSetMax( bar, max );
- LCSetValue( bar, value );
-
- // if value exceeds max then the bottom of the destRect is above
- // the bottom of the view rectangle: we need to scroll the text downward
-
- if ( value > max )
- ScrollBarChanged( window );
-
- SetPort( savePort );
-
- return;
- }
-
-
- static void ViewChanged( WindowRef window )
- {
- DocumentHandle hDocument;
- GrafPtr savePort;
- ControlRef bar;
- Rect r;
- LongRect viewRect;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument( window );
-
- // resize the text area
-
- CalcTextRect( window, &r );
- WERectToLongRect( &r, &viewRect );
- WESetViewRect( &viewRect, (*hDocument)->we );
-
- // move and resize the control bars
- // first, the vertical bar
-
- bar = ((*hDocument)->scrollBars).v;
- CalcScrollBarRect( window, v, &r );
- MoveControl( bar, r.left, r.top );
- SizeControl( bar, r.right - r.left, r.bottom - r.top );
- ValidRect( &r );
-
- // now the horizontal bar
-
- bar = ((*hDocument)->scrollBars).h;
- CalcScrollBarRect( window, h, &r );
- MoveControl( bar, r.left, r.top );
- SizeControl( bar, r.right - r.left, r.bottom - r.top );
- ValidRect( &r );
-
- // reset the thumb positions and the max values of the control bars
- AdjustBars( window );
-
- // redraw the control bars
- ShowControl( ((*hDocument)->scrollBars).v );
- ShowControl( ((*hDocument)->scrollBars).h );
-
- SetPort( savePort );
-
- return;
- }
-
- /*
- This is a deviation from the original Pascal WASTE Demo App code.
-
- This "morally correct" code for window dragging is per an article in MacTech
- Magazine (July 1994, Vol 10, No. 7). by Eric Shapiro (of Rock Ridge Enterprises)
- called "Multiple Monitors vs. Your Application"
-
- Eric addressed numerous things to allow your app to deal nicely with multiple
- monitor setups, one of them is dragging.
-
- According to Eric, many apps don't let you drag windows to second monitors, and
- though holding down the cmd/opt keys often overrides this problem, it should
- still be updated. And the only reason qd.screenBits.bounds works to allow
- you to drag to second monitors is because of a kludge Apple put in the Window Manager
-
- So, this is some code from Eric to make our app be "morally correct" :)
- */
-
- void DoDrag( Point thePoint, WindowRef window )
- {
- Rect limitR;
-
- if ( gHasColorQD )
- limitR = ( **GetGrayRgn()).rgnBBox;
- else
- limitR = qd.screenBits.bounds;
-
- DragWindow( window, thePoint, &limitR );
-
- return;
- }
-
-
- void Resize( Point newSize, WindowRef window )
- {
- DocumentHandle hDocument;
- GrafPtr savePort;
- Rect r;
- RgnHandle tempRgn, dirtyRgn;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument( window );
-
- // create temporarty regions for calculations
- tempRgn = NewRgn();
- dirtyRgn = NewRgn();
-
- // save old text region
-
- CalcTextRect( window, &r );
- RectRgn( tempRgn, &r );
-
- // erase the old grow icon rect
- CalcGrowIconRect( window, &r );
- EraseRect( &r );
-
- // hide the scroll bars
-
- HideControl( ((*hDocument)->scrollBars).v );
- HideControl( ((*hDocument)->scrollBars).h );
-
- // perform the actual resizing of the window, redraw scroll bars and grow icon
- SizeWindow( window, newSize.h, newSize.v, false );
- ViewChanged( window );
- MyDrawGrowIcon( window, true );
-
- // calculate the dirty region (to be updated)
- CalcTextRect( window, &r );
- RectRgn( dirtyRgn, &r );
- XorRgn( dirtyRgn, tempRgn, dirtyRgn );
- InsetRect( &r, -kTextMargin, -kTextMargin );
- RectRgn( tempRgn, &r );
- SectRgn( dirtyRgn, tempRgn, dirtyRgn );
-
- // mark the dirty region as invalid
- InvalRgn( dirtyRgn );
-
- // throw away temporary regions
- DisposeRgn( tempRgn );
- DisposeRgn( dirtyRgn );
-
- SetPort( savePort );
-
- return;
- }
-
- void DoGrow( Point hitPt, WindowRef window )
- {
- Rect sizeRect;
- long newSize;
- Point tempPoint;
-
- SetRect( &sizeRect, kMinWindowWidth, kMinWindowHeight, SHRT_MAX, SHRT_MAX );
- newSize = GrowWindow( window, hitPt, &sizeRect );
-
- // In the WASTE Demo App source, Marco typecasted newSize to a type Point. Can't
- // do that in C (but you can, obviously, in Pascal).
- // But there is a trick! The Point structure is 32-bits, with the v value
- // in the hi word and the h value in the low word. So, we can just separate
- // them out. Neat huh?
-
- if ( newSize != 0 )
- {
- tempPoint.v = HiWrd( newSize );
- tempPoint.h = LoWrd( newSize );
-
- Resize( tempPoint, window );
- }
- return;
- }
-
-
- void DoZoom( short partCode, WindowRef window )
- {
- DocumentHandle hDocument;
- GrafPtr savePort;
- Rect r;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument(window);
-
- r = GetWindowPort( window )->portRect;
- EraseRect( &r );
- HideControl( ((*hDocument)->scrollBars).v );
- HideControl( ((*hDocument)->scrollBars).h );
-
- ZoomWindow( window, partCode, false );
-
- ViewChanged( window );
- CalcTextRect( window, &r );
- InvalRect( &r );
-
- SetPort( savePort );
-
- return;
- }
-
- // this is a callback tourine called by the Toolbox Control Manager
- // move the scroll bar thumb and scroll the text accordingly
-
- static pascal void ScrollProc( ControlRef bar, ControlPartCode partCode )
- {
- long value, step;
-
- if ( partCode == kControlNoPart )
- return;
-
- value = LCGetValue( bar );
- step = sScrollStep;
-
- if ( (( value < LCGetMax( bar )) && ( step > 0 )) || (( value > 0 ) && ( step < 0 ) ) )
- {
- LCSetValue( bar, value + step );
- ScrollBarChanged( FrontWindow() );
- }
-
- return;
- }
-
- static void DoScrollBar( Point hitPt, EventModifiers modifiers, WindowRef window )
- {
- DocumentHandle hDocument;
- ControlRef bar;
- LongRect viewRect;
- ControlPartCode partCode;
- short step;
-
- hDocument = GetWindowDocument(window);
- WEGetViewRect( &viewRect, (*hDocument)->we );
-
- // find out which scrollbar was hit (if any) and in which part
- partCode = FindControl( hitPt, window, &bar );
-
- if ( bar != NULL )
- {
- // dispatch on partCode
-
- if ( partCode == kControlIndicatorPart )
- {
- // click in thumb: call TrackControl with no actionProc and adjust text
-
- partCode = TrackControl( bar, hitPt, NULL );
- LCSynch( bar );
- ScrollBarChanged( window );
-
- } // end if partCode == kControlIndicatorPart
-
- else
-
- {
- if ( bar == ((*hDocument)->scrollBars).v )
- {
-
- // dispatch our partCode
-
- switch( partCode )
- {
- case kControlUpButtonPart:
- if ( (modifiers & optionKey ) == 0 )
- step = -kScrollDelta;
- else
- step = -1;
-
- break;
-
- case kControlDownButtonPart:
- if ( (modifiers & optionKey ) == 0 )
- step = +kScrollDelta;
- else
- step = 1;
-
- break;
-
- case kControlPageUpPart:
- step = -( viewRect.bottom - viewRect.top) + kScrollDelta;
-
- break;
-
- case kControlPageDownPart:
- step = ( viewRect.bottom - viewRect.top ) - kScrollDelta;
-
- break;
-
- default:
- step = 0;
- }
- }
- else if ( bar == ((*hDocument)->scrollBars).h )
- {
-
- // dispatch our partCode
-
- switch( partCode )
- {
- case kControlUpButtonPart:
- if ( (modifiers & optionKey ) == 0 )
- step = -kScrollDelta;
- else
- step = -1;
-
- break;
-
- case kControlDownButtonPart:
- if ( (modifiers & optionKey ) == 0 )
- step = +kScrollDelta;
- else
- step = 1;
-
- break;
-
- case kControlPageUpPart:
- step = -( viewRect.right - viewRect.left) + kScrollDelta;
-
- break;
-
- case kControlPageDownPart:
- step = ( viewRect.right - viewRect.left ) - kScrollDelta;
-
- break;
-
- default:
- step = 0;
- }
- }
-
- // save step in a static variable for our ScrollProc callback
-
- sScrollStep = step;
-
- // track the mouse
-
- if ( sScrollProc == NULL )
- sScrollProc = NewControlActionProc( ScrollProc );
- partCode = TrackControl( bar, hitPt, sScrollProc );
- }
-
- }
-
- return;
- }
-
-
- /*
- This is a callback routine called whenever the text is scrolled automaticall.
- Since auto-scrolling is enabled, WEScroll may be invoked internally by WASTE
- in many different circumstances, and we want to be notified when this happens
- so we can adjust the scroll bars
- */
-
- static pascal void TextScrolled( WEReference we )
- {
- WindowRef window = NULL;
-
- // retrieve the window pointer stored in the WE instance as a "reference constant"
-
- if (WEGetInfo(weRefCon, &window, we) != noErr )
- return;
-
- // make sure the scroll bars are in synch with the destination rectangle
-
- AdjustBars( window );
-
- return;
- }
-
-
- Boolean DoContent( Point hitPt, const EventRecord *event, WindowRef window )
- {
- WEReference we;
- Boolean inBackground, handleClick;
- Rect textRect;
- GrafPtr savePort;
- Boolean result = false; // false means click should not activate this window
-
- we = GetWindowWE(window);
-
- // is this windowd in the background?
-
- if ( IsWindowHilited( window ) )
- inBackground = false;
- else
- inBackground = true;
-
-
- // set the port to our window's port
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- // convert the point to local coordinates
-
- GlobalToLocal( &hitPt );
-
- // a click in an inactive window should normally activate it,
- // but the availability of the Drag Manager introduces an exception to this rule:
- // a click in the background selection may start a drag gesture,
- // without activating the window
-
- if ( inBackground )
- {
- if ( gHasDragAndDrop )
- {
- long selStart, selEnd;
- RgnHandle selRgn;
-
- WEGetSelection( &selStart, &selEnd, we );
- selRgn = WEGetHiliteRgn( selStart, selEnd, we );
- handleClick = PtInRgn( hitPt, selRgn ) && WaitMouseMoved( event->where );
- DisposeRgn( selRgn );
- }
- else
- handleClick = false; // no DragManager: never click-through
- }
- else
- handleClick = true; // window is frontmost: always handle click
-
- if ( handleClick )
- {
- CalcTextRect( window, &textRect );
-
- if ( PtInRect( hitPt, &textRect ) )
- WEClick( hitPt, event->modifiers, event->when, we );
- else
- DoScrollBar( hitPt, event->modifiers, window );
- }
- else
- result = inBackground;
-
- // restore the port
-
- SetPort( savePort );
-
-
- return result;
- }
-
-
- static void DoScrollKey( SignedByte keyCode, WindowRef window )
- {
- DocumentHandle hDocument;
- ControlRef bar;
- long v;
- LongRect viewRect;
-
- hDocument = GetWindowDocument(window);
- bar = ((*hDocument)->scrollBars).v;
-
- // get current scroll bar value
-
- v = LCGetValue( bar );
-
- // get text view rect
-
- WEGetViewRect( &viewRect, (*hDocument)->we );
-
- switch ( keyCode )
- {
-
- case keyPgUp:
- v -= ( viewRect.bottom - viewRect.top ) + kScrollDelta;
- break;
-
- case keyPgDn:
- v += ( viewRect.bottom - viewRect.top ) - kScrollDelta;
- break;
-
- case keyHome:
- v = 0;
- break;
-
- case keyEnd:
- v = LONG_MAX;
- break;
-
- default:
- break;
- } // end switch keyCode
-
-
- // set the new scroll bar value and scroll the text pane accordingly
-
- LCSetValue( bar, v );
- ScrollBarChanged( window );
-
- return;
- }
-
-
- void DoKey( char key, const EventRecord *event )
- {
- WindowRef window;
- SignedByte keyCode;
-
- window = FrontWindow();
-
- // do nothing if no window is active
-
- if ( window == NULL )
- return;
-
- // extract virtual key code from event record
-
- // keyCode = ( event->message & keyCodeMask ) >> 8;
- keyCode = BSR( BAND(event->message, keyCodeMask ), 8 );
-
- // page movement keys are handled by HsoiDoScrollKey()
-
- switch ( keyCode )
- {
- case keyPgUp:
- case keyPgDn:
- case keyHome:
- case keyEnd:
- DoScrollKey( keyCode, window );
- break;
-
- default:
- WEKey( key, event->modifiers, GetWindowWE(window) );
- break;
- }
-
- return;
- }
-
- void DoUpdate( WindowRef window )
- {
- GrafPtr savePort;
- RgnHandle updateRgn;
-
- // if we have no windows, there's nothing to update!
-
- if ( window == NULL )
- return;
-
- // save the old drawing port
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- // notify everything that we're doing an update.
-
- BeginUpdate( window );
-
- // BeginUpdate sets the window port visRgn to the region to update
-
- updateRgn = GetWindowPort(window)->visRgn;
-
- if ( !EmptyRgn( updateRgn ) ) // if it's not an empty region, let's update it!
- {
-
- // erase the update region
- EraseRgn( updateRgn );
-
- // draw scroll bars
- UpdateControls( window, updateRgn );
-
- // draw grow icon
- MyDrawGrowIcon( window, false );
-
- // draw text
- WEUpdate( updateRgn, GetWindowWE( window ) );
-
- }
-
- // tell everything we're done updating
-
- EndUpdate( window );
-
- // restore the old graphics port
-
- SetPort( savePort );
-
-
- return;
- }
-
-
- void DoActivate( Boolean activFlag, WindowRef window )
- {
- DocumentHandle hDocument;
- WEReference we;
- GrafPtr savePort;
- ControlPartCode barHilite;
- Rect barRect;
- short menuID;
-
- // if there aren't any windows, nothing to do here...
-
- if (window == NULL)
- return;
-
- hDocument = GetWindowDocument(window);
- we = (*hDocument)->we;
-
- // set up the port
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- // activate or deactivate the text (and any other relevant stuff) depending on just
- // what we're doing here...
-
-
- if ( activFlag )
- {
- WEActivate( we );
- barHilite = kControlNoPart;
- }
- else
- {
- WEDeactivate( we );
- barHilite = kControlDisabledPart;
- }
-
-
- // redraw the grow icon (and validate it's rect)
-
- MyDrawGrowIcon( window, true );
-
- // redraw the scroll bars with the new highlighting (and validate their rects)
- // first, the vertical scroll bar
-
- HiliteControl( ((*hDocument)->scrollBars).v, barHilite );
- CalcScrollBarRect( window, v, &barRect );
- ValidRect( &barRect );
-
- // now the horizontal scroll bar
-
- HiliteControl( ((*hDocument)->scrollBars).h, barHilite );
- CalcScrollBarRect( window, h, &barRect );
- ValidRect( &barRect );
-
- // dim or undim text-related menus
-
- for ( menuID = kMenuEdit; menuID <= kMenuFeatures; menuID++ )
- {
- if ( activeFlag )
- EnableItem( GetMenuHandle( menuID ), 0 );
- else
- DisableItem( GetMenuHandle( menuID ), 0 );
- }
-
- // invalidate the menu bar
-
- InvalMenuBar();
-
- // restore the old graphics port..
-
- SetPort( savePort );
-
- return;
- }
-
- OSErr CreateWindow( const FSSpec *pFileSpec )
- {
- DocumentHandle hDocument;
- WindowRef window;
- WEReference we;
- ControlRef bar;
- FInfo fileInfo;
- Rect textRect;
- LongRect longTextRect;
- OSErr err = noErr;
- AliasHandle alHandle;
-
-
- // allocate a relocateable block to hold a document record
-
- hDocument = (DocumentHandle) NewHandleClear( sizeof( DocumentRecord ) );
- err = MemError();
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // create the window from a 'WIND' template: the window is initially invisible
- // if ColorQuickDraw is available, create a color window
-
- if ( gHasColorQD )
- window = GetNewCWindow( kWindowTemplateID, NULL, (WindowRef) -1L );
- else
- window = GetNewWindow( kWindowTemplateID, NULL, (WindowRef) -1L );
-
- // make sure we got a window
-
- if ( window == NULL )
- {
- err = memFullErr;
- ErrorAlert( err );
- return err;
- }
-
- // link the document record to the window and the other way around
-
- SetWRefCon(window, (long) hDocument);
- (*hDocument)->owner = window;
-
- // we got a window, so tell QuickDraw where to draw...
-
- SetPortWindowPort( window );
-
- // calculate the text rectangle
-
- CalcTextRect( window, &textRect );
- WERectToLongRect( &textRect, &longTextRect );
-
- // create new WASTE instance
- err = WENew( &longTextRect, &longTextRect, weDoAutoScroll +
- weDoOutlineHilite +
- weDoUndo +
- weDoIntCutAndPaste +
- weDoDragAndDrop +
- weDoUseTempMem +
- weDoDrawOffscreen, &we);
-
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // set the alignment to weFlushLeft so "slop recalc" is disabled
-
- WESetAlignment( weFlushLeft, we );
-
-
- // save a reference to the window in the WE instance
- err = WESetInfo( weRefCon, &window, we );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // now the other way around: save the WE reference in the document record
-
- (*hDocument)->we = we;
-
- // create routine descriptors for the WASTE callbacks
-
- if ( sWEScroller == NULL )
- {
- sWEScroller = NewWEScrollProc( TextScrolled );
- sWEDragTranslator = NewWETranslateDragProc( TranslateDrag );
- }
-
- // set up our callbacks
-
- err = WESetInfo( weScrollProc, &sWEScroller, we );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- err = WESetInfo( weTranslateDragHook, &sWEDragTranslator, we );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // create a scroll bar from a 'CNTL' template
-
- // first vertical
-
- bar = GetNewControl( kScrollBarTemplateID, window );
- if ( bar == NULL )
- {
- err = memFullErr;
- ErrorAlert( err );
- return err;
- }
-
- HiliteControl( bar, kControlDisabledPart );
-
- // attach a LongControl record to the scroll bar: this allows us to use long
- // settings and thus scroll text taller than 32,767 pixels
-
- err = LCAttach( bar );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // save control handle in the document record
-
- ((*hDocument)->scrollBars).v = bar;
-
- // now horizontal
-
- bar = GetNewControl( kScrollBarTemplateID, window );
- if ( bar == NULL )
- {
- err = memFullErr;
- ErrorAlert( err );
- return err;
- }
-
- HiliteControl( bar, kControlDisabledPart );
-
- // attach a LongControl record to the scroll bar: this allows us to use long
- // settings and thus scroll text taller than 32,767 pixels
-
- err = LCAttach( bar );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // save control handle in the document record
-
- ((*hDocument)->scrollBars).h = bar;
-
- // ViewChanged() adjusts the scroll bars rectangles to the window frame
-
- ViewChanged( window );
-
- // if pFileSpec is not NULL, it points to a file to read, so let's read it!
-
- if ( pFileSpec != NULL )
- {
- // turn the cursor into a wristwatch because this can be a lengthy operation
-
- SetCursor( *(GetCursor(watchCursor)) );
-
- // retrieve file infomation
-
- err = FSpGetFInfo( pFileSpec, &fileInfo );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // make sure we recognize the file type
-
- if ( (fileInfo.fdType != kTypeText ) && ( fileInfo.fdType != kTypeTextReadOnly ) )
- {
- err = -1;
- ErrorAlert( err );
- return err;
- }
-
- // read in the file
- err = ReadTextFile( pFileSpec, we );
- if ( err != noErr )
- {
- ErrorAlert( err );
- return err;
- }
-
- // you _could_ call WECalText here and recalculate the line breaks,
- // but it's really unnecessary, and just tends to slow things down
-
- // set the window title to the file name
- SetWTitle( window, pFileSpec->name );
-
- // create an alias to keep track of the file
- err = NewAlias( NULL, pFileSpec, &alHandle );
- (*hDocument)->fileAlias = (Handle)alHandle;
-
- // if the file is a read-only file (type 'ttro'), go ahead and enable
- // those flags
-
- if (fileInfo.fdType == kTypeTextReadOnly )
- WEFeatureFlag( weFReadOnly, weBitSet, we );
-
- // let's make sure the cursor is happy...
- InitCursor();
-
- } // end pFileSpec != NULL
- else
- (*hDocument)->fileAlias = NULL;
-
- skipit:
-
- // adjust scroll bar settings based on the total text height
-
- AdjustBars( window );
-
- // finally! show the document window
-
- ShowWindow( window );
-
- return err;
- }
-
-
- void DestroyWindow( WindowRef window )
- {
- DocumentHandle hDocument;
- short menuID;
-
- hDocument = GetWindowDocument(window);
-
- // destroy the WE record
-
- WEDispose( (*hDocument)->we );
-
- // destory the LongControl records attached to the scroll bars
-
- LCDetach( ((*hDocument)->scrollBars).v );
- LCDetach( ((*hDocument)->scrollBars).h );
-
- // dispose of the file alias, if any
-
- ForgetHandle( & ((*hDocument)->fileAlias) );
-
- // destroy the window record and all associated data structures
-
- DisposeWindow( window );
-
- // finally, dispose of the document record
-
- DisposeHandle( (Handle) hDocument );
-
- // adjust the menus to suit
-
- for ( menuID = kMenuFont; menuID <= kMenuFeatures; menuID++ )
- DisableItem( GetMenuHandle( menuID ), 0 );
- InvalMenuBar();
-
- return;
- }
-